﻿using System.Windows;
using JDKD.BMCS.Common;
using JDKD.BMCS.Model;
using NutShell.DesignPattern;
using System;
using System.ComponentModel;
using System.Diagnostics;

namespace JDKD.BMCS.Business
{
        /// <summary>
        /// 表示监控区域
        /// </summary>
        public class Area : INotifyPropertyChanged
        {
                #region 构造函数

                /// <summary>
                /// 初始化监控区域
                /// </summary>
                /// <param name="model">监控区域数据模型</param>
                public Area(AreaModel model)
                {
                        Model = model;
                        IsSelected = false;
                }

                #endregion 构造函数

                #region 常量
                public const int Margin = 10;
                public const int BackOffset = 20;
                public const int Threshold = 45;
                #endregion

                #region 字段

                private byte[,] forePixels = new byte[Global.AeraHeight, Global.AeraWidth];
                private byte[,] backPixels = new byte[Global.BackHeight, Global.BackWidth];

                private byte averageBackPixel;

                #endregion

                #region 属性

                public int CameraId
                {
                        get
                        {
                                return Model.CameraId;
                        }
                }

                public int ChannelId
                {
                        get
                        {
                                return SegmentId;
                        }
                }

                public int SegmentId
                {
                        get
                        {
                                return Model.SegmentId;
                        }
                }

                public int X
                {
                        get
                        {
                                return Model.X;
                        }
                        set
                        {
                                Model.X = value;
                        }
                }

                public int Y
                {
                        get
                        {
                                return Model.Y;
                        }
                        set
                        {
                                Model.Y = value;
                        }
                }

                /// <summary>
                /// 获取或属性摄像机数据模型
                /// </summary>
                public AreaModel Model { get; protected set; }

                /// <summary>
                /// 获取或设置摄像机所属采集卡
                /// </summary>
                public GraphicsCard GraphicsCard
                {
                        get
                        {
                                return Camera.GraphicsCard;
                        }
                }

                public Camera Camera
                {
                        get
                        {
                                return Singleton<BusinessCache>.Instance.Cameras[CameraId];
                        }
                }

                public int Left
                {
                        get
                        {
                                return X - Global.AeraWidth / 2;
                        }
                }

                public int Top
                {
                        get
                        {
                                return Y - Global.AeraHeight / 2;
                        }
                }

                public int Right
                {
                        get
                        {
                                return X + Global.AeraWidth / 2;
                        }
                }

                public int Bottom
                {
                        get
                        {
                                return Y + Global.AeraHeight / 2;
                        }
                }

                public int BackLeft
                {
                        get
                        {
                                return X + BackOffset - Global.BackWidth / 2;
                        }
                }

                public int BackRight
                {
                        get
                        {
                                return X + BackOffset + Global.BackWidth / 2;
                        }
                }

                public int BackTop
                {
                        get
                        {
                                return Y - Global.BackHeight / 2;
                        }
                }

                public int BackBottom
                {
                        get
                        {
                                return Y + Global.BackHeight / 2;
                        }
                }

                public bool IsFront
                {
                        get
                        {
                                return CameraId % 2 == 1 ? true : false;
                        }
                }

                public Visibility RaiseVisibility
                {
                        get
                        {
                                if (IsFront)
                                {
                                        return System.Windows.Visibility.Visible;
                                }
                                return Visibility.Collapsed;
                        }
                }

                public Visibility ShiftVisibility
                {
                        get
                        {
                                if (IsFront)
                                {
                                        return System.Windows.Visibility.Collapsed;
                                }
                                return Visibility.Visible;
                        }
                }

                public bool IsSelected { get; private set; }

                public bool IsFull { get; private set; }


                #endregion 属性

                #region 事件

                public event PropertyChangedEventHandler PropertyChanged;

                #endregion 事件

                #region 方法

                public bool HitTest(int x, int y)
                {
                        if (x > Left
                                && x < Right
                                && y > Top
                                && y < Bottom)
                        {
                                IsSelected = true;
                        }
                        return IsSelected;
                }

                public void UnHitTest()
                {
                        IsSelected = false;
                }

                public void Analyse()
                {
                        UpdateBackPixels();

                        UpdateForePixels();

                        int total = 0;
                        for (int y = 0; y < Global.AeraHeight; y++)
                        {
                                for (int x = 0; x < Global.AeraWidth; x++)
                                {
                                        if (forePixels[y,x] > 0)
                                        {
                                                total++;
                                        }
                                }
                        }

                        IsFull = total > Global.AeraWidth * Global.AeraHeight * 0.85;
                }

                private void UpdateForePixels()
                {
                        int pixel = 0;

                        for (int y = 0; y < Global.AeraHeight; y++)
                        {
                                for (int x = 0; x < Global.AeraWidth; x++)
                                {
                                        pixel = GetPixel(Left + x, Top + y) - averageBackPixel - Threshold;

                                        if (pixel < 0)
                                        {
                                                forePixels[y, x] = 0;
                                        }
                                        else if (pixel > 255)
                                        {
                                                forePixels[y, x] = 255;
                                        }
                                        else
                                        {
                                                forePixels[y, x] = (byte)pixel;
                                        }
                                        
                                }
                        }
                }

                private void UpdateBackPixels()
                {
                        long total = 0;
                        for (int y = 0; y < Global.BackHeight; y++)
                        {
                                for (int x = 0; x < Global.BackWidth; x++)
                                {
                                        total += GetPixel(BackLeft + x, BackTop + y);
                                }
                        }

                        averageBackPixel = (Byte)(total / (Global.BackWidth * Global.BackHeight));

                        Trace.WriteLine(CameraId.ToString() + " " + ChannelId.ToString() + "  " + averageBackPixel);
                }



                private unsafe byte GetPixel(int x, int y)
                {
                        long position = (Global.ImageCaptureHeight - y - 1) * Global.ImageCaptureWidth + x - 1;
                        return Camera.ImageBuffer[position];
                }

                public void OnPropertyChanged(string propertyName)
                {
                        if (PropertyChanged != null)
                        {
                                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                        }
                }

                #endregion 方法
        }
}